package com.shijiezhijia.sjzjapp.annotation_compiler;

import com.google.auto.service.AutoService;
import com.shijiezhijia.sjzjapp.anntations.BindView;
import com.shijiezhijia.sjzjapp.anntations.IBinder;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;

import static com.shijiezhijia.sjzjapp.annotation_compiler.KeyWord.*;


/**
 * @Author tzc
 * @Time 2022/11/17 0017
 * Describe 描述  具有相同功能只是对象和资源传参值不同就可以考取自动生成~
 * 注解处理器 处理自己需要拦截的注解，实现自定义功能
 * 由javac调用
 * java文件-->通过javac命令（在该命令执行过程中会调用【注解处理器APT】处理相关注解）--->class文件
 * 具体在 process 中处理逻辑 生成java代码
 *
 *
 * */
@AutoService(Process.class)
public class AnnotationCompiler extends AbstractProcessor {

    /**配置：1.支持的版本 可以选择*/
    @Override
    public SourceVersion getSupportedSourceVersion() {
        //最新版本
        return SourceVersion.latestSupported();
    }

    /**2.能用来处理哪些注释*/
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        HashSet<String> set=new HashSet<>();
        set.add(BindView.class.getCanonicalName());
        return set;
    }

    /**定义一个用来生成APT目录下文件的对象 在初始化函数中拿初始值*/
    Filer filer;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        filer=processingEnv.getFiler();
    }

    /**
     * @param annotations 我们代码里面所有注解对应的Element
     *                    类注解   对应 TypeElement
     *                    方法注解 对应 ExecutableElement
     *                    字段注解 对应 VariableElement
     * @param roundEnv
     * @return
     */
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (annotations==null||annotations.size()<1){
            return false;
        }
        //打印日志
        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,"tzc-----"+ annotations);

        //拿指定Element
        Set<? extends Element> set=roundEnv.getElementsAnnotatedWith(BindView.class);
        //这部分是自己的逻辑了
        //遍历 使用activity名做key 进行分类
        Map<String, List<VariableElement>> map=new HashMap<>();
        for (Element element:set){
            //BindView是注释在字段上的 所以可以强转VariableElement
            VariableElement variableElement= (VariableElement) element;

            String activityName=variableElement.getEnclosingElement().getSimpleName().toString();
            List<VariableElement> list=map.get(activityName);
            if (list==null){
                list=new ArrayList<>();
                map.put(activityName,list);
            }
            list.add(variableElement);
        }
        buildFile(map);
        return false;
    }
    private void buildFile( Map<String, List<VariableElement>> map){
        //输入控件 用来向文件中写入数据
        Writer writer = null;
        Iterator<String> iterator=map.keySet().iterator();
        while (iterator.hasNext()){
            //key
           String activityName= iterator.next();
           //value
            List<VariableElement> variableElements=map.get(activityName);
            //包名
            String packageName=processingEnv.getElementUtils().getPackageOf(variableElements.get(0)).toString();
            try {
                //创建需要生成的文件 activity对应的binding文件
                JavaFileObject sourceFile=filer.createSourceFile(packageName+"."+activityName+"_ViewBinding");
                writer=sourceFile.openWriter();
                //package com.shijiezhijia.sjzjapp.demo;
                writer.append(PACKAGE+" "+packageName+" ;\n ");
                //import com.shijiezhijia.sjzjapp.anntations.IBinder;
                writer.append(IMPORT+" "+ IBinder.class.getName() +";\n");
                //public class MainActivity_ViewBinding implements IBinder<com.shijiezhijia.sjzjapp.demo.MainActivity>{
                writer.append(PUBLIC+" "+CLASS+" "+activityName+"_ViewBinding"+" "+IMPLEMENTS+" IBinder<"+packageName+"."+activityName+">{\n");
                //@Override
                writer.append("@"+OVERRIDE+"\n");
                //public void bind(com.shijiezhijia.sjzjapp.demo.MainActivity target){
                 writer.append(PUBLIC+" "+VOID+" bind("+packageName+"."+activityName+" target){\n");
                for (VariableElement element:variableElements){
                    //target.textView=(android.widget.TextView)target.findViewById(214563211120);
                    //TODO 变量名element.getSimpleName() 变量类型 element.asType() 变量id:element.getAnnotation(BindView.class).value()
                    writer.append("target."+element.getSimpleName()+"=("+element.asType()+")target.findViewById("+element.getAnnotation(BindView.class).value()+");\n");
                }
                //}}
                writer.append("}\n}\n");
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if (writer!=null){
                    try {
                        writer.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}